package org.oimwrapper.connectors.common;

import org.oimwrapper.connectors.*;

/**
 * Clears all recon events on the system.<p>
 *
 * This task expects the following parameters, in addition to the standard
 * parameters in the {@link OIMTaskBase} class.
 * <ul>
 * <li><code>MaxToDelete</code> The maximum number of records to delete before committing 
 *                              the changes.</li>
 * <li><code>Statuses</code> A comma separated list of the recon event statuses to purge.</li>
 * <li><code>Resources</code> A comma separated list of the recon target object types to
 *                            purge events for.</li>
 * <li><code>StartDate</code> Specifies that events created before this date will not be 
 *                            cleared.  The date is specified in MM/dd/yyyy format.</li>
 * <li><code>EndDate</code> Specifies that events created after this date will not be 
 *                          cleared.  The date is specified in MM/dd/yyyy format.</li>
 * </ul>
 */
public class OIMClearReconEvents extends OIMTaskBase {

	/**
	 * True if a stop has been requested for this task.
	 */
	private boolean stop;

	/**
	 * Default constructor.
	 */
	public OIMClearReconEvents() {
		super("OIMWRAPPER.TASK");
		stop = false;
	}

	/**
	 * This method is called by the scheduler to execute the task instance.
	 */
	public void execute() {
		try {
			int size = Integer.parseInt(getDefaultAttribute("MaxToDelete", "100000"));
			String[] statuses = getDefaultAttribute("Statuses", "Event Linked,Event Closed").split(",");
			String[] resources = getDefaultAttribute("Resources", "*").split(",");
            String startDate = getDefaultAttribute("StartDate", "");
            String endDate = getDefaultAttribute("EndDate", "");
			logger.warn("Clearing all matching recon events...");
			String clause = "";
			if (!isWildcard(statuses)) {
				clause += " and rce_key in (select rce_key from rce where rce_status in (";
				for (int i = 0; i < statuses.length; i++) {
					if (i > 0) {
						clause += ", ";
					}
					clause += "'" + statuses[i].trim() + "'";
				}
				clause += "))";
			}
			if (!isWildcard(resources)) {
				clause += " and rce_key in (select rce_key from rce where obj_key in (";
				for (int i = 0; i < resources.length; i++) {
					if (i > 0) {
						clause += ", ";
					}
					clause += Long.toString(getResourceObject(resources[i]));
				}
				clause += "))";
			}
            if (!isEmpty(startDate) || !isEmpty(endDate)) {
				clause += " and rce_key in (select rce_key from rce ";
                if (!isEmpty(startDate) && !isEmpty(endDate)) {
                    clause += "where rce_create between  to_date('" + startDate + "', 'MM/DD/YYYY')  and to_date('" + endDate + "', 'MM/DD/YYYY')";
                } else if (!isEmpty(startDate) && isEmpty(endDate)) {
                    clause += "where rce_create >= to_date('" + startDate + "', 'MM/DD/YYYY')";
                } else if (!isEmpty(endDate) && isEmpty(startDate)) {
                    clause += "where rce_create <= to_date('" + endDate + "', 'MM/DD/YYYY')";
                }
				clause += ")";
            }
			logger.debug("clause = " + clause);
			executeOimQuery("update rpc set rpc_parent_rpc_key = null where rpc_parent_rpc_key is not null " + clause);
			executeOimQuery("update rcm set rcm_parent_rcm_key = null where rcm_parent_rcm_key is not null " + clause);
			String[] tables = new String[] {"rpc", "rcm", "rca", "rcb", "rcd", "rch", "rcp", "rcu", "rce"};
			for (int i = 0; !stop && i < tables.length; i++) {
				clearTable(tables[i], size, clause);
			}
			logger.warn("All matching recon events have been cleared.");
		} catch (Exception e) {
			OIMExceptionHandler.handleException(logger, e, getClass());
		}
	}

	/**
	 * This method is called by the scheduler to stop a running task instance.
	 * 
	 * @return <code>true</code>
	 */
	public boolean stop() {
		logger.warn(" ---- Stopping current task ---- ");
		stop = true;
		return stop;
	}
	
	/**
	 * Checks if an array of possible items is just a wildcard.
	 * 
	 * @param Items The array of items to check.
	 * @return <code>true</code> if the items array is a wildcard, or <code>false</code>
	 *         if it isn't.
	 */
	protected boolean isWildcard(String[] Items) {
		return (Items.length == 0 || (Items.length == 1 && Items[0].equals("*")));
	}
	
	/**
	 * Clears out a table incrementally.
	 * 
	 * @param Table The name of the table to clear.
	 * @param Size The number of rows to clear per pass.
	 * @param Clause An additional cluase to use to filter certain event types.
	 * @exception Exception
	 */
	protected void clearTable(String Table, int Size, String Clause) throws Exception {
		for (int i = 1; !stop; i += Size) {
			logger.warn("Clearing rows " + Integer.toString(i) + " to " + Integer.toString(i + Size - 1) + " from " + Table);
			String query = "select count(*) as RECORD_COUNT from " + Table + " where rownum > 0 " + Clause;
			String count = (String) getOimData(query)[0].get("RECORD_COUNT");
			logger.debug("remaining records = " + count);
			if (count.equals("0")) {
				break;
			}
			executeOimQuery("delete from " + Table + " where rownum < " + Integer.toString(Size) + Clause);
		}
	}
}